<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script type="text/javascript" src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/vue/2.6.14/vue.min.js"></script><script type="text/javascript" src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-y/Mock.js/1.0.0/mock-min.js"></script>
    <meta name="author" content="lijinbo" />
    <title>使用IntersectionObserver加载元素做下拉加载更多</title>
    <style>
      .loading_box {
        display: flex;
        align-items: center;
        justify-content: center;
      }
    </style>
  </head>

  <body>
    <div id="app">
      <p>
        文章参考：
        <a href="https://www.douyin.com/video/7124897535587601668" target="_blank">
          一个监听元素重叠的前端开发实战技巧
        </a>
      </p>
      <p>此方案不用监听滚动条而是监听元素的位置，相对来说会节省很多的性能开销</p>
      <ol>
        <li v-for="(item, index) in list" :key="index" class="user_box">
          <img :src="item.headerImg" />
          <span>{{ item.name }}</span>
          <p>{{ item.content }}</p>
        </li>
      </ol>
      <div class="loading_box">
        <img src="../../../../static/css/loading-42234a73.gif" />
      </div>
    </div>
    <script>
      new Vue({
        el: '#app',
        data() {
          return {
            isLoading: false,
            list: []
          }
        },
        created() {
          this.getList()
        },
        mounted() {
          const loadingDom = document.querySelector('.loading_box')
          const observer = new IntersectionObserver(
            (nodes) => {
              nodes.forEach((v) => {
                // 判断加载图标是否进入可视区域
                if (v.isIntersecting && !this.isLoading) {
                  console.log('加载更多')
                  this.getList()
                }
              })
            },
            // 监听的元素和视口重叠的大小
            { threshold: 0.1 }
          )
          observer.observe(loadingDom)
        },
        methods: {
          getList() {
            const res = Mock.mock({
              'list|10': [
                {
                  name: '@cname()',
                  headerImg: '@image(50x50, @hex)',
                  content: '@cparagraph(2,20)'
                }
              ]
            })
            // 模拟数据请求
            this.isLoading = true
            setTimeout(() => {
              this.isLoading = false
              this.list.push(...res.list)
            }, 500)
          }
        }
      })
    </script>
  </body>
</html>
